package com.gitee.hermer.engine.jars.app.sdk.proxy;



import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

import org.springframework.aop.SpringProxy;
import org.springframework.context.ApplicationContext;

import com.gitee.hermer.boot.jee.commons.exception.ErrorCode;
import com.gitee.hermer.boot.jee.commons.log.UtilsContext;
import com.gitee.hermer.boot.jee.commons.verify.Assert;
import com.gitee.hermer.engine.jars.core.annotate.EngineAppReference;
import com.gitee.hermer.engine.jars.core.app.domain.EngineAppJobContext;
import com.gitee.hermer.engine.jars.core.domain.EngineConstant;
import com.gitee.hermer.engine.jars.core.execute.manage.IEngineExecutePoolManager;

public class ExecuteProxy extends UtilsContext implements InvocationHandler, Serializable,SpringProxy {
	
	private final ApplicationContext applicationContext; //self Context
	
	public ExecuteProxy(ApplicationContext applicationContext){
		this.applicationContext = applicationContext;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if(method.getName().equals("toString")){
			return this.toString();
		}else if(method.getName().equals("equals")){
			return this.equals(args[0]);
		}else{
			EngineAppReference reference = method.getAnnotation(EngineAppReference.class);
			if(reference != null){
				Field h = proxy.getClass().getSuperclass().getDeclaredField("h");  
				h.setAccessible(true);  
				final Object aopProxy = h.get(reference);  
				Field memberValues = aopProxy.getClass().getDeclaredField("memberValues");
				memberValues.setAccessible(true);
				final Map<String,String> values = (Map<String,String>) memberValues.get(aopProxy);
				String appName = values.get(EngineConstant.ANNOTATE_FIELD_NAME_APP_NAME);
				String appVersion = values.get(EngineConstant.ANNOTATE_FIELD_NAME_APP_VERSION);
				String workMethod = values.get(EngineConstant.ANNOTATE_FIELD_NAME_WORK_METHOD);
				String workVersion = values.get(EngineConstant.ANNOTATE_FIELD_NAME_WORK_VERSION);
				
				Assert.hasTextCode(appName, ErrorCode.SYSTEM_ERROR,"@EngineReference字段appName不可为空");
				Assert.hasTextCode(appVersion, ErrorCode.SYSTEM_ERROR,"@EngineReference字段appVersion不可为空");
				Assert.hasTextCode(workMethod, ErrorCode.SYSTEM_ERROR,"@EngineReference字段workMethod不可为空");
				Assert.hasTextCode(workVersion, ErrorCode.SYSTEM_ERROR,"@EngineReference字段workVersion不可为空");
				
				IEngineExecutePoolManager executePoolManager = applicationContext.getBean(EngineAppJobContext.class).getParentContext().getBean(IEngineExecutePoolManager.class);
				return executePoolManager.execute(appName,appVersion,workMethod,workVersion,args);
			}
			return null;
		}
	}

}
